﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MacomberMapSystem.Common.Database;
using WeifenLuo.WinFormsUI.Docking;
using MacomberMapSystem.Common.Serialization;
using System.Runtime.InteropServices;
using System.Xml;
using MacomberMapSystem.Common.Internals;
using MacomberMapSystem.Common.CIM;
using System.Threading;
using System.Collections;
using MacomberMapSystem.Common.User_Interfaces.One_Lines;

namespace MacomberMapSystem.Common.User_Interfaces.Database
{
    /// <summary>
    /// This form displays a list of all users, along with their list of assignments
    /// </summary>
    public partial class frmUserAssignments : DockContent
    {
        #region Variable declarations
        /// <summary>The data repository associated with the user information</summary>
        private MM_Repository Repository;
        #endregion

        #region Initialization
        /// <summary>
        /// Initialize a new user assignments form
        /// </summary>
        /// <param name="Repository">The repository that may contain additionally needed elements</param>
        /// <param name="Users">The collection of user</param>
        public frmUserAssignments(MM_Repository Repository, Dictionary<int, MM_Database_User> Users)
        {
            InitializeComponent();
            this.Repository = Repository;
            this.lvOneLines.OneLineEditor = this.OneLineEditor;
            SortedDictionary<String, MM_Database_User> SortedUsers = new SortedDictionary<string, MM_Database_User>();
            foreach (MM_Database_User User in Users.Values)
                SortedUsers.Add(User.Nickname, User);

            foreach (MM_Database_User User in SortedUsers.Values)
                if (User.Equals(Repository.CurrentUser) || User.AssignedOneLines > 0)
                    AddUser(User);
        }

        /// <summary>
        /// When the form is shown, sort everything.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnShown(EventArgs e)
        {
            splMain_SplitterMoved(splMain, new SplitterEventArgs(0, 0, 0, 0));
            base.OnShown(e);
        }

        /// <summary>
        /// Add a user to our list view
        /// </summary>
        /// <param name="User"></param>
        private ListViewItem AddUser(MM_Database_User User)
        {
            ilPictures.Images.Add(User.UserName, User.UserImage);

            ListViewItem lvI = new ListViewItem(User.Nickname, User.UserName);
            lvI.Tag = User;
            lvI.Name = User.FullName;
            lvI.Font = new Font(this.Font, FontStyle.Bold);
            lvI.SubItems.Add(User.AssignedOneLines.ToString("#,##0") + " assigned / " + User.AssignedFixes.ToString("#,##0") + " fixes needed.");
            lvI.SubItems.Add(User.CompletedOneLines.ToString("#,##0") + " completed.");
            lvI.SubItems.Add(User.CompletedFixes.ToString("#,##0") + " fixes made.");
            lvI.SubItems.Add("Status: " + User.UserState.ToString());


            if (User.HandleErrors && User.HandleWarnings)
                lvI.SubItems.Add("Topology & Appearance updating");
            else if (User.HandleErrors)
                lvI.SubItems.Add("Topology updating");
            else if (User.HandleWarnings)
                lvI.SubItems.Add("Appearance updating");
            else
                lvI.SubItems.Add("Administrator");
            lvI.SubItems.Add(User.UserNote).ForeColor = Color.Blue;
            lvUsers.Items.Add(lvI);
            return lvI;
        }

        /// <summary>
        /// Update the information on our user
        /// </summary>
        /// <param name="User"></param>
        private void UpdateUser(MM_Database_User User)
        {
            //Refresh the done and completed count
            Repository.Db.UpdateUserCounts(User);

            //Locate, and create/destroy the list item as needed          
            ListViewItem lvI = lvUsers.Items[User.FullName];
            if (User.AssignedOneLines == 0 && !User.Equals(Repository.CurrentUser))
            {
                if (lvI != null)
                {
                    lvUsers.Items.Remove(lvI);
                    lvI = null;
                }
                return;
            }
            else if (lvI == null)
                lvI = AddUser(User);

            

            lvI.Text = User.Nickname;
            lvI.SubItems[1].Text = User.AssignedOneLines.ToString("#,##0") + " assigned / " + User.AssignedFixes.ToString("#,##0") + " fixes needed.";
            lvI.SubItems[2].Text = User.CompletedOneLines.ToString("#,##0") + " completed.";
            lvI.SubItems[3].Text = User.CompletedFixes.ToString("#,##0") + " fixes made.";
            lvI.SubItems[4].Text = "Status: " + User.UserState.ToString();

            if (User.HandleErrors && User.HandleWarnings)
                lvI.SubItems[5].Text = "Topology & Appearance updating";
            else if (User.HandleErrors)
                lvI.SubItems[5].Text = "Topology updating";
            else if (User.HandleWarnings)
                lvI.SubItems[5].Text = "Appearance updating";
            else
                lvI.SubItems[5].Text = "Administrator";
            lvI.SubItems[6].Text = User.UserNote;
        }




        #endregion

        /// <summary>
        /// When the user's selection changes, pull in the list of one-lines associated with that
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lvUsers_SelectedIndexChanged(object sender, EventArgs e)
        {
            lvOneLines.Items.Clear();
            if (lvUsers.SelectedItems.Count == 1)
            {
                tmrUpdate_Tick(tmrUpdate, EventArgs.Empty);
                splMain.Panel2Collapsed = false;

                MM_Database_User User = lvUsers.SelectedItems[0].Tag as MM_Database_User;

                //Pull in our list of assignments for our user
                lvOneLines.Initialize(Repository, User);
            }
            else
            {
                tmrUpdate_Tick(tmrUpdate, EventArgs.Empty);
                splMain.Panel2Collapsed = true;
            }

        }




        
        /// <summary>
        /// Update our tile size based on the main split
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void splMain_SplitterMoved(object sender, SplitterEventArgs e)
        {
            lvUsers.TileSize = new Size(lvUsers.DisplayRectangle.Width - 5, lvUsers.TileSize.Height);
        }

        /// <summary>
        /// Handle a menu item being clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmsMain_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            if (cmsMain.Tag is MM_Database_User && e.ClickedItem.Tag is String)
                System.Diagnostics.Process.Start("mailto:" + (string)e.ClickedItem.Tag);
            else if (e.ClickedItem.Text == "Edit My &Profile")
            {
                MM_Database_User SelUser = (cmsMain.Tag as List<MM_Database_User>)[0];
                using (frmUserProfileEditor Profile = new frmUserProfileEditor(SelUser, Repository.Db))
                    if (Profile.ShowDialog() == DialogResult.OK)
                        Profile.EditingUser.UpdateRdb(Repository);
            }
            else if (e.ClickedItem.Text == "Audit my &completed one-lines")
            {
                WeifenLuo.WinFormsUI.Docking.DockPanel TargetPanel = null;
                Form FormToCheck = this.ParentForm;
                do
                {
                    foreach (Control ctl in FormToCheck.Controls)
                        if (ctl is WeifenLuo.WinFormsUI.Docking.DockPanel)
                            TargetPanel = ctl as WeifenLuo.WinFormsUI.Docking.DockPanel;
                    FormToCheck = FormToCheck.ParentForm;
                } while (TargetPanel == null && FormToCheck != null);

                new frmOneLineAudit(Repository.CurrentUser, Repository.Db).Show(TargetPanel);
            }
            else if (e.ClickedItem.Text == "Audit &completed one-lines")
            {
                WeifenLuo.WinFormsUI.Docking.DockPanel TargetPanel = null;
                Form FormToCheck = this.ParentForm;
                do
                {
                    foreach (Control ctl in FormToCheck.Controls)
                        if (ctl is WeifenLuo.WinFormsUI.Docking.DockPanel)
                            TargetPanel = ctl as WeifenLuo.WinFormsUI.Docking.DockPanel;
                    FormToCheck = FormToCheck.ParentForm;
                } while (TargetPanel == null && FormToCheck != null);

                new frmOneLineAudit((MM_Database_User)e.ClickedItem.Tag, Repository.Db).Show(TargetPanel);
            }
#if Communicator
            else if (cmsMain.Tag is List<MM_Database_User> && e.ClickedItem.Tag is CommunicatorAPI.IMessengerAdvanced)
            {                
                CommunicatorAPI.IMessengerAdvanced msg = e.ClickedItem.Tag as CommunicatorAPI.IMessengerAdvanced;
                List<Object> OutUsers = new List<object>();
                foreach (MM_Database_User User in cmsMain.Tag as List<MM_Database_User>)
                    OutUsers.Add(User.Email);
                try
                {
                    Convert.ToInt64(msg.StartConversation(CommunicatorAPI.CONVERSATION_TYPE.CONVERSATION_TYPE_IM, OutUsers.ToArray(), null, Application.ProductName, "1", null));
                }
                catch (COMException ex)
                {
                    MessageBox.Show("Error opening IM window: " + ex.Message);
                }
            }
#endif
            else if (cmsMain.Tag is MM_Database_Assignment)
                using (frmAlternateOneLineEvaluator AlternateEvaluator = new frmAlternateOneLineEvaluator(cmsMain.Tag as MM_Database_Assignment))
                    if (AlternateEvaluator.ShowDialog() == DialogResult.OK)
                        lvOneLines.ctlOneLineAssignments_SelectedIndexChanged(lvOneLines, EventArgs.Empty);


        }

        /// <summary>
        /// Handle a mouse click on the users menue
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lvUsers_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                ListViewHitTestInfo hti = (sender as ListView).HitTest(e.Location);
                if (hti.Item == null)
                    return;
                cmsMain.Tag = hti.Item.Tag;
                cmsMain.Items.Clear();

                if (cmsMain.Tag is MM_Database_User)
                {
                    List<MM_Database_User> SelectedUsers = new List<MM_Database_User>();
                    List<String> Emails = new List<string>();
                    foreach (ListViewItem lvI in lvUsers.SelectedItems)
                    {
                        SelectedUsers.Add(lvI.Tag as MM_Database_User);
                        Emails.Add((lvI.Tag as MM_Database_User).Email);
                    }
                    cmsMain.Tag = SelectedUsers;

                    if (SelectedUsers.Count == 1)
                        cmsMain.Items.Add(SelectedUsers[0].Nickname + " (" + SelectedUsers[0].UserName + ")").Enabled = false;
                    else
                        cmsMain.Items.Add(SelectedUsers.Count.ToString("#,##0") + " users").Enabled = false;

                    cmsMain.Items.Add("-");
                    cmsMain.Items.Add("Send &email").Tag = String.Join(",", Emails.ToArray());
                    //See if office communicator is running
#if Communicator
                    try
                    {
                        cmsMain.Items.Add("Send &IM").Tag = new CommunicatorAPI.MessengerClass() as CommunicatorAPI.IMessengerAdvanced;
                    }
                    catch (Exception)
                    { }
#endif
                    if (SelectedUsers.Count == 1 && String.Equals(SelectedUsers[0].UserName, Repository.UserDomain + "\\" + Repository.UserName, StringComparison.CurrentCultureIgnoreCase))
                    {
                        cmsMain.Items.Add("Edit My &Profile");
                        cmsMain.Items.Add("Audit my &completed one-lines");
                    }
                    else if (SelectedUsers.Count == 1)
                        cmsMain.Items.Add("Audit &completed one-lines").Tag = SelectedUsers[0];

                }

                else if (cmsMain.Tag is MM_Database_Assignment)
                {
                    MM_Database_Assignment Assignment = cmsMain.Tag as MM_Database_Assignment;
                    MM_Database_OneLine OneLine = Assignment.GetOneLine(Repository);
                    cmsMain.Items.Add("One-line " + String.Join(" / ", OneLine.Names)).Enabled = false;
                    cmsMain.Items.Add("-");
                    cmsMain.Items.Add("&Open one-line").Tag = OneLine;
                    cmsMain.Items.Add("&Search for alternative one-lines").Tag = Assignment;
                }

                if (cmsMain.Items.Count > 0)
                    cmsMain.Show(sender as Control, e.Location);
            }
        }

        /// <summary>
        /// Handle the saving of a one-line
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OneLineEditor_OneLineSaved(object sender, EventArgs e)
        {
            //Remove our assignemnt 
            ListViewItem ToRemove = lvOneLines.Items["a" + OneLineEditor.Assignment.ID.ToString()];
            int OldIndex = ToRemove.Index;
            lvOneLines.Items.Remove(ToRemove);
            lvOneLines.SelectedIndices.Clear();
            if (OldIndex < lvOneLines.Items.Count)
                lvOneLines.SelectedIndices.Add(OldIndex);
            else if (lvOneLines.Items.Count > 0)
                lvOneLines.SelectedIndices.Add(lvOneLines.Items.Count - 1);
            tmrUpdate_Tick(this, EventArgs.Empty);
        }

        /// <summary>
        /// Refresh our count of all users' completed one-lines
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tmrUpdate_Tick(object sender, EventArgs e)
        {
            //Update all of our users
            foreach (MM_Database_User User in Repository.User_Collection.Values)
                try
                {
                    UpdateUser(User);
                }
                catch (Exception ex) 
                {
                    //Console.WriteLine("Error updating user " + User.FullName + ": " + ex.ToString());
                }
        }

    
        
    }
}